package com.flqy.baselibrary.utils;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.LinearInterpolator;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import com.flqy.baselibrary.R;
import com.gyf.immersionbar.ImmersionBar;
import com.jakewharton.rxbinding2.view.RxView;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

import io.reactivex.functions.Consumer;

/**
 * Created by ludaiqian on 16/7/6.
 */
public class ViewUtils {


    private static long lastClickTime;

    /**
     * 防止快速点击
     *
     * @return
     */
    public static boolean isFastDoubleClick() {
        return isFastDoubleClick(500);
    }

    /**
     * 防止快速点击
     *
     * @return
     */
    public static boolean isFastDoubleClick(int limit) {
        long time = System.currentTimeMillis();
        long timeD = time - lastClickTime;
        if (limit < timeD) {
//            lastClickTime = time;
            return false;
        }
        lastClickTime = time;
        return true;
    }
    /**
     * 获取状态栏高度
     *
     * @param context
     * @return
     */
    public static int getStatusBarHeight(Activity context) {
       return ImmersionBar.getStatusBarHeight(context);
    }

    public static Point center(Activity context, int width, int height) {
        int x = ScreenUtil.getScreenWidth() / 2 - width / 2;
        int offset = getStatusBarHeight(context);
        int contentHeight = ScreenUtil.getScreenHeight() - getStatusBarHeight(context);
        int y = contentHeight / 2 - height / 2 + offset;
        return new Point(x, y);

    }

    public static void showSoftInputFromWindow(EditText view) {
        InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (!imm.isActive(view)) {
            imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }
    public static void showSoftInputFromWindow(Activity activity, EditText editText) {
        editText.setFocusable(true);
        editText.setFocusableInTouchMode(true);
        editText.requestFocus();
        //显示软键盘
//        activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        //如果上面的代码没有弹出软键盘 可以使用下面另一种方式
        //InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
        // imm.showSoftInput(editText, 0);

        //打开软键盘
        InputMethodManager imm = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(editText, 0);

    }


    public static void hideSoftInputFromWindow(Context mContext, View view) {
        InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }

    public static final String RIGHT_IN = "right-in";
    public static final String BOTTOM_IN = "bottom-in";
    public static final String LEFT_OUT = "left-out";
    public static final String NONE = "none";
    public static void anima(String animation, Activity ac) {
        switch (animation) {

            case RIGHT_IN:
                ac.overridePendingTransition(R.anim.slide_in_right,
                        R.anim.slide_out_left);
                break;
            case BOTTOM_IN:
                ac.overridePendingTransition(R.anim.abc_slide_in_bottom,
                        R.anim.slide_out_top);
                break;
            case LEFT_OUT:
                ac.overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
            case "none":
            default:
                break;
        }
    }

    public static Rect getViewFrameRect(Activity context, View v) {
//        Rect frame = new Rect();
//        getActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
//        int statusBarHeight = frame.top;
//
//        int[] location = new int[2];
//        view.getLocationOnScreen(location);
//        location[1] += statusBarHeight;
//
//        int width = view.getWidth();
//        int height = view.getHeight();
        Rect frame = new Rect();
        context.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
        int statusBarHeight = frame.top;

        int[] location = new int[2];
        v.getLocationOnScreen(location);
        location[1] += statusBarHeight;

        int width = v.getWidth();
        int height = v.getHeight();
        return new Rect(location[0], location[1], location[0] + width, location[1] + height);
    }


    public static void paddingToNavigationBar(Activity context,View view) {
        if (!hasSoftKeys(view.getContext()) || !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT))
            return;
        Method method = null;
        try {
            method = view.getClass().getMethod("setClipToPadding", boolean.class);
        } catch (NoSuchMethodException e) {
            return;
        }
        try {
            method.invoke(view, false);
            view.setPadding(0, 0, 0, getNavigationBarHeight(context));
        } catch (IllegalAccessException e) {
            return;
        } catch (InvocationTargetException e) {
            return;
        }
    }


    public static boolean isTouchedView(View v, MotionEvent event) {
//        if (v != null && (v instanceof EditText)) {
        int[] leftTop = {0, 0};
        // 获取输入框当前的location位置
        v.getLocationInWindow(leftTop);
        int left = leftTop[0];
        int top = leftTop[1];
        int bottom = top + v.getHeight();
        int right = left + v.getWidth();
        if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
            // 点击的是输入框区域，保留点击EditText的事件
            return true;
        } else {
            return false;
        }
//        }
//        return false;
    }

    /**
     * 取导航栏高度
     *
     * @return
     */
    public static int getNavigationBarHeight(Activity ctx) {
        return ImmersionBar.getNavigationBarHeight(ctx);
    }

    public static boolean hasSoftKeys(Context ctx) {
        boolean hasSoftwareKeys;
        WindowManager manager = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Display d = manager.getDefaultDisplay();

            DisplayMetrics realDisplayMetrics = new DisplayMetrics();
            d.getRealMetrics(realDisplayMetrics);

            int realHeight = realDisplayMetrics.heightPixels;
            int realWidth = realDisplayMetrics.widthPixels;

            DisplayMetrics displayMetrics = new DisplayMetrics();
            d.getMetrics(displayMetrics);

            int displayHeight = displayMetrics.heightPixels;
            int displayWidth = displayMetrics.widthPixels;

            hasSoftwareKeys = (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
        } else {
            boolean hasMenuKey = ViewConfiguration.get(ctx).hasPermanentMenuKey();
            boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
            hasSoftwareKeys = !hasMenuKey && !hasBackKey;
        }
        return hasSoftwareKeys;
    }


    public static void paddingToStatusBar(Activity context,View view) {
        if (!(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)) return;
        view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + ViewUtils.getStatusBarHeight(context), view.getPaddingRight(), view.getPaddingBottom());
        // view.setPadding(0, ViewUtils.getStatusBarHeight(view.getContext()), 0, 0);
    }

    @SuppressWarnings("unchecked")
    public static <T extends View> T find(View parent, int viewId) {
        return (T) parent.findViewById(viewId);
    }

    @SuppressWarnings("unchecked")
    public static <T extends View> T find(Activity activity, int viewId) {
        return (T) activity.findViewById(viewId);
    }

    @SuppressWarnings("unchecked")
    public static <T extends ViewGroup.LayoutParams> T getParams(View view) {
        return (T) view.getLayoutParams();
    }

    public static ViewGroup.MarginLayoutParams getMarginParams(View view) {
        return getParams(view);
    }

    public static FrameLayout.LayoutParams getFrameParams(View view) {
        return getParams(view);
    }

    public static RelativeLayout.LayoutParams getRelativeParams(View view) {
        return getParams(view);
    }

    public static LinearLayout.LayoutParams getLinearParams(View view) {
        return getParams(view);
    }

    @SuppressWarnings("unchecked")
    public static <T extends View> T inflate(Context context, int layoutId) {
        return (T) LayoutInflater.from(context).inflate(layoutId, null, false);
    }

    public static <T extends View> T inflate(View root, int layoutId) {
        return inflateInternal(root, layoutId, false);
    }

    public static <T extends View> T inflateAndAttach(View root, int layoutId) {
        return inflateInternal(root, layoutId, true);
    }

    @SuppressWarnings("unchecked")
    private static <T extends View> T inflateInternal(View root, int layoutId, boolean attach) {
        if (root == null) throw new NullPointerException("Root view cannot be null");
        return (T) LayoutInflater.from(root.getContext()).inflate(layoutId, (ViewGroup) root, attach);
    }

    public static void showScaleEnter(View v, Animator.AnimatorListener l) {
        PropertyValuesHolder pl = PropertyValuesHolder.ofFloat("alpha", 0f, 1f);
        PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("scaleX", 0f, 1f);
        PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("scaleY", 0f, 1f);
        PropertyValuesHolder p4 = PropertyValuesHolder.ofObject("backgroundColor", new ArgbEvaluator(), Color.TRANSPARENT, Color.BLACK);
        ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(v, pl, p2, p3, p4);
//        animator.setStartDelay(200);
        animator.setDuration(300).start();
        if (l != null) {
            animator.addListener(l);
        }
    }

    public static void showScaleExist(View v, Animator.AnimatorListener l) {
        PropertyValuesHolder pl = PropertyValuesHolder.ofFloat("alpha", 1f, 0f);
        PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0f);
        PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f);
        PropertyValuesHolder p4 = PropertyValuesHolder.ofObject("backgroundColor", new ArgbEvaluator(), Color.BLACK, Color.TRANSPARENT);
        ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(v, pl, p2, p3, p4);
        animator.setDuration(300).start();
        if (l != null) {
            animator.addListener(l);
        }
    }

    /**
     * Used to set the ripple animation when a tab is selected
     *
     * @param clickedView       the view that is clicked (to get dimens where ripple starts)
     * @param backgroundView    temporary view to which final background color is set
     * @param bgOverlay         temporary view which is animated to get ripple effect
     * @param rippleColor       the ripple color
     * @param animationDuration duration for which animation runs
     */
    public static void setBackgroundWithRipple(View clickedView, final View backgroundView,
                                               final View bgOverlay, final int rippleColor, int animationDuration) {
        int centerX = (int) (clickedView.getX() + (clickedView.getMeasuredWidth() / 2));
        int centerY = clickedView.getMeasuredHeight() / 2;
        int finalRadius = backgroundView.getWidth();

        backgroundView.clearAnimation();
        bgOverlay.clearAnimation();

        Animator circularReveal;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            circularReveal = ViewAnimationUtils
                    .createCircularReveal(bgOverlay, centerX, centerY, 0, finalRadius);
        } else {
            bgOverlay.setAlpha(0);
            circularReveal = ObjectAnimator.ofFloat(bgOverlay, "alpha", 0, 1);
        }

        circularReveal.setDuration(animationDuration);
        circularReveal.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                onCancel();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                onCancel();
            }

            private void onCancel() {
//                backgroundView.setBackgroundColor(newColor);
                bgOverlay.setVisibility(View.GONE);
            }
        });

        bgOverlay.setBackgroundColor(rippleColor);
        bgOverlay.setVisibility(View.VISIBLE);
        circularReveal.start();
    }

    public static int getScaledTouchSlop(Context context) {
        return ViewConfiguration.get(context).getScaledTouchSlop();
    }

    public static int getImageMaxEdge() {
        return (int) (165.0 / 320.0 * ScreenUtil.getScreenWidth());
    }

    /**
     * 防止过快点击
     *
     * @param view
     * @param onClickListener
     */
    public static void setOnClickListener(final View view, final View.OnClickListener onClickListener) {
        RxView.clicks(view)
                .throttleFirst(500, TimeUnit.MILLISECONDS)
                .subscribe(new Consumer<Object>() {
                    @Override
                    public void accept(Object o) throws Exception {
                        onClickListener.onClick(view);
                    }
                });
    }
    /**
     *  修改状态栏文字颜色，这里小米，魅族区别对待。
     */
    public static void setLightStatusBar(final Activity activity, final boolean dark) {
        L.i("UI_","setLightStatusBar");
        setLightStatusBar(activity.getWindow(),dark);
    }
    public static void setLightStatusBar(final Window window, final boolean dark) {
        L.i("UI_","setLightStatusBar");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

            if(DeviceHelper.isFlyme()){
                setFlymeLightStatusBar(window, dark);
            }else if(DeviceHelper.isMIUI()){
                MIUISetStatusBarLightMode(window, dark);
            }else {
                setAndroidNativeLightStatusBar(window, dark);
            }

        }
    }


    public static boolean MIUISetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            Class clazz = window.getClass();
            try {
                int darkModeFlag = 0;
                Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                if (dark) {
                    extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
                } else {
                    extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
                }
                result = true;

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && DeviceHelper.isMiUIV7OrAbove()) {
                    //开发版 7.7.13 及以后版本采用了系统API，旧方法无效但不会报错，所以两个方式都要加上
                    if (dark) {
                       window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                    } else {
                        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
                    }
                }
            } catch (Exception e) {

            }
        }
        return result;
    }

    private static boolean setFlymeLightStatusBar(Window window, boolean dark) {
        boolean result = false;

            try {
                WindowManager.LayoutParams lp = window.getAttributes();
                Field darkFlag = WindowManager.LayoutParams.class
                        .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                Field meizuFlags = WindowManager.LayoutParams.class
                        .getDeclaredField("meizuFlags");
                darkFlag.setAccessible(true);
                meizuFlags.setAccessible(true);
                int bit = darkFlag.getInt(null);
                int value = meizuFlags.getInt(lp);
                if (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
                result = true;
            } catch (Exception e) {
            }
        return result;
    }

    private static void setAndroidNativeLightStatusBar(Window window, boolean dark) {
        View decor = window.getDecorView();
        if (dark) {
            decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        } else {
            decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        }
    }

    /**
     * 获取软件盘的高度
     * @return
     */
    public static int getSupportSoftInputHeight(Activity activity) {
        Rect r = new Rect();
        /**
         * decorView是window中的最顶层view，可以从window中通过getDecorView获取到decorView。
         * 通过decorView获取到程序显示的区域，包括标题栏，但不包括状态栏。
         */
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
        //获取屏幕的高度
        int screenHeight = activity.getWindow().getDecorView().getRootView().getHeight();
        //计算软件盘的高度
        int softInputHeight = screenHeight - r.bottom;

        /**
         * 某些Android版本下，没有显示软键盘时减出来的高度总是144，而不是零，
         * 这是因为高度是包括了虚拟按键栏的(例如华为系列)，所以在API Level高于20时，
         * 我们需要减去底部虚拟按键栏的高度（如果有的话）
         */
        if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.KITKAT_WATCH) {
            // When SDK Level >= 20 (Android L), the softInputHeight will contain the height of softButtonsBar (if has)
            softInputHeight = softInputHeight - getSoftButtonsBarHeight(activity);
        }
        return softInputHeight;
    }


    /**
     * 底部虚拟按键栏的高度
     * @return
     */
    public static  int getSoftButtonsBarHeight(Activity activity) {
        DisplayMetrics metrics = new DisplayMetrics();
        //这个方法获取可能不是真实屏幕的高度
        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int usableHeight = metrics.heightPixels;
        //获取当前屏幕的真实高度
        activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
        int realHeight = metrics.heightPixels;
        if (realHeight > usableHeight) {
            return realHeight - usableHeight;
        } else {
            return 0;
        }
    }

    public static Activity getActivityFrom(View view) {
        if (null != view) {
            Activity context = getActivityFrom(view.getContext());
            if (context != null) return context;

        }
        return null;

    }

    public static Activity getActivityFrom(Context context) {
        if (context instanceof Activity) {
            return (Activity) context;
        }
        while (context instanceof ContextWrapper) {
            if (context instanceof Activity) {
                return (Activity) context;
            }
            context = ((ContextWrapper) context).getBaseContext();
        }
        return null;
    }

    public static void scaleAnim(final View target, final long duration, long startDelay, final float scaleFrom, final float scaleTo, final boolean withZ) {
//        Log.i("ppppp","delay="+startDelay);
        ViewPropertyAnimator anim = target.animate().scaleX(scaleTo).scaleY(scaleTo);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP&&withZ) {
            anim.z(scaleTo);
        }
        anim.setDuration(duration).setStartDelay(startDelay).setListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (target.getScaleX() > 1f) {
                    ViewPropertyAnimator anim = target.animate().scaleX(scaleFrom).scaleY(scaleFrom);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP&&withZ) {
                        anim.z(scaleFrom);
                    }
                    anim.setDuration(duration);
                    if(anim.getStartDelay()!=0) {
                        anim.setStartDelay(0);
                    }
                } else {
                    ViewPropertyAnimator anim = target.animate().scaleX(scaleTo).scaleY(scaleTo);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP&&withZ) {
                        anim.z(scaleTo);
                    }
                    anim.setDuration(duration);
                    if(anim.getStartDelay()!=0) {
                        anim.setStartDelay(0);
                    }
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        }).start();
    }

    public static void rotateAnim(View target, long duration) {
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(target, "rotation", 360f);;
        objectAnimator.setDuration(duration);
        objectAnimator.setInterpolator(new LinearInterpolator());
        objectAnimator.setRepeatMode(ValueAnimator.RESTART);
        objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
        objectAnimator.start();
    }
}
